home *** CD-ROM | disk | FTP | other *** search
/ Scene Storm / Scene Storm - Volume 1.iso / coding / c / fontmaker / bmfd / bmfd.c < prev    next >
C/C++ Source or Header  |  1995-11-05  |  13KB  |  514 lines

  1. /*
  2.  * BMFD: BitMapFontDisassembler.
  3.  *
  4.  * © Copyright 1993 by Olaf 'Rhialto' Seibert. All rights reserved.
  5.  *
  6.  * For use with BMFC (BitMapFontCompiler) by Adam M. Costello.
  7.  */
  8.  
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <ctype.h>
  13.  
  14. #define INTUI_V36_NAMES_ONLY
  15. #include <utility/tagitem.h>
  16. #include <intuition/intuition.h>
  17. #include <clib/exec_protos.h>
  18. #include <clib/alib_protos.h>
  19. #include <clib/graphics_protos.h>
  20. #include <clib/intuition_protos.h>
  21. #include <clib/diskfont_protos.h>
  22. #include <clib/utility_protos.h>
  23.  
  24. void           *IntuitionBase;
  25. void           *GfxBase;
  26. void           *DiskFontBase;
  27. void           *UtilityBase;
  28.  
  29. struct BitMap    BitMap;
  30. struct RastPort DeepRastPort;
  31. struct RastPort *RastPort;
  32. struct Window  *Window;
  33. struct TextFont *Font;
  34. struct TextFont *OldFont;
  35. int        PlanePick = -1;
  36.  
  37. int        linelength;
  38. int        stretch;
  39. int        verbose;
  40.  
  41. struct TagItem WindowTags[] = {
  42.     WA_InnerHeight, 0,        /* (Calculated and set) */
  43.     TAG_END
  44. };
  45. struct ExtNewWindow NewWindow = {
  46.     0, 20,            /* LeftEdge, TopEdge */
  47.     640, 0,            /* Width, Height (calculated and set) */
  48.     1, 1,            /* DetailPen, BlockPen */
  49.     0,                /* IDCMPFlags */
  50.     WFLG_SUPER_BITMAP | WFLG_GIMMEZEROZERO | WFLG_NOCAREREFRESH |
  51.     WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_SIZEGADGET |
  52.        WFLG_SIZEBRIGHT | WFLG_NW_EXTENDED, /* Flags */
  53.     NULL,            /* FirstGadget */
  54.     NULL,            /* CheckMark */
  55.     NULL,            /* Title */
  56.     NULL,            /* Screen */
  57.     &BitMap,            /* BitMap */
  58.     20,20, -1,-1,        /* Min/Max Width/Height */
  59.     WBENCHSCREEN,        /* Type */
  60.     WindowTags
  61. };
  62.  
  63. struct TagItem TextTags[] = {
  64.     TAG_IGNORE, 0,
  65.     TAG_END
  66. };
  67. struct TTextAttr TextAttr = {
  68.     "topaz.font", 8, FSF_TAGGED, 0, TextTags
  69. };
  70.  
  71. char ColorChars[] = "_#23456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  72.                   "abcdefghijklmnopqrstuvwxyz"
  73.                   "=+";
  74.  
  75. #define RASTERWIDTH        640
  76. #define min(x, y)           ((x) < (y)? (x): (y))
  77.  
  78. void
  79. openall(void)
  80. {
  81.     int         depth;
  82.     int         i;
  83.  
  84.     /* Libraries */
  85.     IntuitionBase = OpenLibrary("intuition.library", 33);
  86.     if (IntuitionBase == NULL) {
  87.     fprintf(stderr, "Needs intuition V33+.\n");
  88.     exit(10);
  89.     }
  90.     GfxBase = OpenLibrary("graphics.library", 33);
  91.     if (GfxBase == NULL) {
  92.     fprintf(stderr, "Needs gfx V33+.\n");
  93.     exit(10);
  94.     }
  95.     DiskFontBase = OpenLibrary("diskfont.library", 34);
  96.     if (DiskFontBase == NULL) {
  97.     fprintf(stderr, "Needs diskfont V34+.\n");
  98.     exit(10);
  99.     }
  100.     UtilityBase = OpenLibrary("utility.library", 34);
  101.     if (UtilityBase == NULL) {
  102.     fprintf(stderr, "Not a 2.0+ system, eh? We'll do without, then...\n");
  103.     }
  104.     /* Font for window; sorry for the strange order */
  105.     Font = OpenDiskFont((struct TextAttr *)&TextAttr);
  106.     if (Font == NULL) {
  107.     fprintf(stderr, "No %s %d!\n", TextAttr.tta_Name, TextAttr.tta_YSize);
  108.     exit(10);
  109.     }
  110.     NewWindow.Height = Font->tf_YSize + 16; /* slight safety fudge */
  111.     WindowTags[0].ti_Data = Font->tf_YSize; /* this is the right way */
  112.     /* Raster for text */
  113.     if (Font->tf_Style & FSF_COLORFONT) {
  114.     struct ColorTextFont *ctf = (struct ColorTextFont *)Font;
  115.  
  116.     depth = ctf->ctf_Depth;
  117.     } else
  118.     depth = 1;
  119.  
  120.     InitBitMap(&BitMap, depth, RASTERWIDTH, NewWindow.Height);
  121.  
  122.     for(i = 0; i < depth; i++) {
  123.     if ((BitMap.Planes[i] = AllocRaster(RASTERWIDTH, BitMap.Rows)) == NULL) {
  124.         fprintf(stderr, "No plane %d\n", i);
  125.         exit(10);
  126.     }
  127.     }
  128.     /* Window for raster. For showing-off purposes only. */
  129.     if ((Window = OpenWindow(&NewWindow)) == NULL) {
  130.     fprintf(stderr, "No window (probably too large). Will do without.\n");
  131.     }
  132.     if (Window && Window->WScreen->RastPort.BitMap->Depth >= depth) {
  133.     /* If possible, use the safely clipped/layered RastPort */
  134.     RastPort = Window->RPort;
  135.     } else {
  136.     /* Otherwise, use the one which has the risk of overrunning */
  137.     RastPort = &DeepRastPort;
  138.     InitRastPort(RastPort);
  139.     RastPort->BitMap = &BitMap;
  140.     }
  141.     OldFont = RastPort->Font;
  142.     SetFont(RastPort, Font);
  143.     SetAPen(RastPort, 1);
  144.     SetBPen(RastPort, 0);
  145.     SetDrMd(RastPort, JAM2);
  146.  
  147. #if 0
  148.     /* testing stuff: */
  149.     {
  150.     int i;
  151.  
  152.     for (i = 0; i < Font->tf_HiChar-Font->tf_LoChar+1; i++)
  153.         printf("%d data %08lx space %04x kern %04x\n",
  154.         i + Font->tf_LoChar,
  155.         *((long *)Font->tf_CharLoc + i),
  156.         *((short *)Font->tf_CharSpace + i),
  157.         *((short *)Font->tf_CharKern + i)
  158.         );
  159.     }
  160. #endif
  161. }
  162.  
  163. /*
  164.  * Clean up system stuff in case of exit
  165.  */
  166. void
  167. cleanup(void)
  168. {
  169.     if (Font) {
  170.     if ((Font->tf_Style & FSF_COLORFONT) && PlanePick != -1) {
  171.         struct ColorTextFont *ctf = (struct ColorTextFont *)Font;
  172.  
  173.         ctf->ctf_PlanePick = PlanePick;
  174.     }
  175.     SetFont(RastPort, OldFont);
  176.     CloseFont(Font);
  177.     }
  178.     if (Window) {
  179.     CloseWindow(Window);
  180.     }
  181.     if (GfxBase) {
  182.     int        i;
  183.  
  184.     for (i = 0; i < BitMap.Depth; i++) {
  185.         if (BitMap.Planes[i]) {
  186.         FreeRaster(BitMap.Planes[i], RASTERWIDTH, BitMap.Rows);
  187.         BitMap.Planes[i] = NULL;
  188.         }
  189.     }
  190.     CloseLibrary(GfxBase);
  191.     }
  192.     if (IntuitionBase) {
  193.     CloseLibrary(IntuitionBase);
  194.     }
  195.     if (DiskFontBase) {
  196.     CloseLibrary(DiskFontBase);
  197.     }
  198.     if (UtilityBase) {
  199.     CloseLibrary(UtilityBase);
  200.     }
  201. }
  202.  
  203. void
  204. header(void)
  205. {
  206.     printf("{********************************\n");
  207.     printf("*                               *\n");
  208.     printf("*   Generated by BMFD 1.00      *\n");
  209.     printf("*                               *\n");
  210.     printf("*    (C) Copyright 1993 by      *\n");
  211.     printf("*   Olaf 'Rhialto' Seibert      *\n");
  212.     printf("*                               *\n");
  213.     printf("********************************}\n");
  214.     printf("\n");
  215. }
  216.  
  217. void
  218. dumpparameters(void)
  219. {
  220.     /* For all fonts: */
  221.  
  222.     printf("bitmapfont %s %d;\n\n",
  223.         Font->tf_Message.mn_Node.ln_Name, Font->tf_YSize);
  224.  
  225.     printf("baseline %d;\n",      Font->tf_Baseline);
  226.     printf("bold %d;\n",         (Font->tf_Style & FSF_BOLD) != 0);
  227.     printf("boldsmear %d;\n",     Font->tf_BoldSmear);
  228.     printf("extended %d;\n",     (Font->tf_Style & FSF_EXTENDED) != 0);
  229.     printf("{ designed %d; }\n", (Font->tf_Flags & FPF_DESIGNED) != 0);
  230.     printf("italic %d;\n",       (Font->tf_Style & FSF_ITALIC) != 0);
  231.     printf("proportional %d;\n", (Font->tf_Flags & FPF_PROPORTIONAL) != 0);
  232.     if (Font->tf_Flags & FPF_DISKFONT) {
  233.     struct DiskFontHeader *df;
  234.     unsigned short *code;
  235.  
  236.     df = (char *)Font - offsetof(struct DiskFontHeader, dfh_TF);
  237.     code = (unsigned short *)df - 2;
  238.  
  239.     printf("returncode %d;\n", *code & 0xFF);
  240.     printf("revision %d;\n", df->dfh_Revision);
  241.     } else {
  242.     printf("returncode 100;\n");
  243.     printf("{ no revision } \n");
  244.     }
  245.     printf("revpath %d;\n", (Font->tf_Flags & FPF_REVPATH) != 0);
  246.     printf("talldot %d;\n", (Font->tf_Flags & FPF_TALLDOT) != 0);
  247.     printf("underlined %d;\n", (Font->tf_Style & FSF_UNDERLINED) != 0);
  248.     printf("widedot %d;\n", (Font->tf_Flags & FPF_WIDEDOT) != 0);
  249.     printf("xsize %d;\n", Font->tf_XSize);
  250.  
  251.     /* For fonts with a TextFontExtension: */
  252.  
  253.     if (UtilityBase) {
  254.     struct TagItem *tag;
  255.     struct TextFontExtension *te;
  256.  
  257.     printf("\n");
  258.  
  259.     te = (void *)Font->tf_Extension;
  260.     if (te->tfe_MatchWord == 0x4E1B &&
  261.         te->tfe_BackPtr == Font) {
  262.  
  263.         printf("{ Font has TextFontExtension; magic word is $%x }\n", te->tfe_MatchWord);
  264.         if (tag = FindTagItem(TA_DeviceDPI, te->tfe_Tags)) {
  265.         printf("xydpi %d %d;\n",
  266.             tag->ti_Data >> 16,
  267.             tag->ti_Data & 0xFFFF);
  268.         }
  269.     }
  270.     } else
  271.     printf("{ Font has no TextFontExtension because it's only 1.2/1.3. }\n");
  272.  
  273.     /* For color fonts: */
  274.  
  275.     if (Font->tf_Style & FSF_COLORFONT) {
  276.     struct ColorTextFont *ctf = (struct ColorTextFont *)Font;
  277.  
  278.     printf("\n");
  279.  
  280.     printf("{ ct_colorfont %d; }\n", (ctf->ctf_Flags & CT_COLORFONT) != 0);
  281.     printf("greyfont %d;\n", (ctf->ctf_Flags & CT_GREYFONT) != 0);
  282.     printf("antialias %d;\n", (ctf->ctf_Flags & CT_ANTIALIAS) != 0);
  283.  
  284.     {
  285.         struct ColorFontColors *cfc = ctf->ctf_ColorFontColors;
  286.         int         i;
  287.  
  288.         if (cfc && cfc->cfc_Count) {
  289.         printf("colors %d", cfc->cfc_Count);
  290.         for (i = 0; i < cfc->cfc_Count; i++) {
  291.             printf(" $%03x", cfc->cfc_ColorTable[i]);
  292.         }
  293.         printf(";\n");
  294.         }
  295.     }
  296.     {
  297.         int         i;
  298.         int         colors;
  299.  
  300.         colors = 1 << ctf->ctf_Depth;
  301.  
  302.         for (i = 0; i < colors; i++) {
  303.         printf("colorsym %c %d\n", ColorChars[i], i);
  304.         }
  305.     }
  306.     printf("depth %d;\n", ctf->ctf_Depth);
  307.     printf("fgcolor %d;\n", ctf->ctf_FgColor);
  308.     printf("high %d;\n", ctf->ctf_High);
  309.     printf("low %d;\n", ctf->ctf_Low);
  310.     printf("planeonoff %d;\n", ctf->ctf_PlaneOnOff);
  311.     printf("planepick %d;\n", ctf->ctf_PlanePick);
  312.     PlanePick = ctf->ctf_PlanePick;
  313.     if (PlanePick != (1 << ctf->ctf_Depth) - 1) {
  314.         fprintf(stderr, "Warning: PlanePick temporarily modified!\n");
  315.         ctf->ctf_PlanePick = (1 << ctf->ctf_Depth) - 1;
  316.     }
  317.     }
  318.  
  319.     printf("\n\n");
  320. }
  321.  
  322. void
  323. dumpsomecharacters(int lo, int hi)
  324. {
  325.     char        output[RASTERWIDTH + 1];
  326.     unsigned char   ch;
  327.     int         i, y;
  328.  
  329.     SetRast(RastPort, 0);
  330.     Move(RastPort, 0, Font->tf_Baseline);
  331.  
  332.     /* Generate begin of command */
  333.     printf("; glyph $%x $%x\n\n", lo, hi);
  334.     printf("{");
  335.     for (i = lo; i <= hi; i++) {
  336.     printf("  $%x:  ", i);
  337.     }
  338.     printf("}\n\n");
  339.  
  340.     memset(output, '_', RASTERWIDTH);
  341.     output[RASTERWIDTH] = '\0';
  342.  
  343.     if (lo == 0x100) {
  344.     /* Try to get the default glyph) */
  345.     if (Font->tf_LoChar > 0)
  346.         lo = Font->tf_LoChar - 1;
  347.     else if (Font->tf_HiChar < 255)
  348.         lo = Font->tf_HiChar + 1;
  349.     else
  350.         printf("{ No default glyph needed }\n");
  351.     hi = lo;
  352.     }
  353.  
  354.     /* plot text in RastPort */
  355.     for (i = lo; i <= hi; i++) {
  356.     ch = i;
  357.     Text(RastPort, &ch, 1);
  358.     if (output[RastPort->cp_x] == ' ') {
  359.         printf("nullglyph $x $x\n", i, i);
  360.         fprintf(stderr, "nullglyph $x\n", i);
  361.     }
  362.  
  363.     if (RastPort->cp_x >= RASTERWIDTH - 1) {
  364.         fprintf(stderr,
  365. "Characters too wide; use -l<n> to specify fewer than %d characters per line.\n",
  366.         i - lo + 1);
  367.         exit(10);
  368.     }
  369.     output[RastPort->cp_x] = ' ';
  370.     output[RastPort->cp_x+1] = ' ';
  371.     Move(RastPort, RastPort->cp_x + 2, RastPort->cp_y);
  372.     }
  373.  
  374.     /* Show off, if needed... */
  375.     if (RastPort == &DeepRastPort)
  376.     CopySBitMap(Window->RPort->Layer);
  377.  
  378.     /* Convert to printable */
  379.     output[RastPort->cp_x - 2] = '\0';
  380.  
  381.     for (y = 0; y < Font->tf_YSize; y++) {
  382.     for (i = 0; output[i]; i++) {
  383.         if (output[i] != ' ') {
  384.         ch = ReadPixel(RastPort, i, y);
  385.         output[i] = ColorChars[ch];
  386.         }
  387.     }
  388.     printf("%s\n", output);
  389.     if (stretch)
  390.         printf("%s\n", output);
  391.     }
  392.     printf("\n\n");
  393. }
  394.  
  395. void
  396. dumpcharacters(void)
  397. {
  398.     int         charsperline;
  399.     int         c;
  400.     int         cn;
  401.  
  402.     if (linelength)
  403.     charsperline = linelength;
  404.     else
  405.     ((charsperline = 64 / Font->tf_XSize) == 0) ? (charsperline = 1) : 0;
  406.  
  407.  
  408.     for (c = Font->tf_LoChar; c <= Font->tf_HiChar; c = cn + 1) {
  409.     cn = min(c + charsperline - 1, Font->tf_HiChar);
  410.     dumpsomecharacters(c, cn);
  411.     }
  412.  
  413.     printf("{ The default glyph: }\n\n");
  414.     dumpsomecharacters(0x100, 0x100);
  415.     printf(";\n");
  416. }
  417.  
  418. void
  419. dupglyphdetect(void)
  420. {
  421.     int         i;
  422.     int         j;
  423.     ULONG       *pi;
  424.     ULONG       *pj;
  425.     UWORD       *pw;
  426.     int         numchars;
  427.     int         output = 0;
  428.  
  429.     numchars = Font->tf_HiChar - Font->tf_LoChar + 2;
  430.  
  431.     for (i = 1; i < numchars; i++) {
  432.     pi = (ULONG *)Font->tf_CharLoc + i;
  433.     for (j = 0; j < i; j++) {
  434.         pj = (ULONG *)Font->tf_CharLoc +j;
  435.         if ((*pi == *pj) &&
  436.         (!(pw = Font->tf_CharSpace) || pw[i] == pw[j]) &&
  437.         (!(pw = Font->tf_CharKern) || pw[i] == pw[j])
  438.         ) {
  439.         if (!output)
  440.             printf("\n{ Duplicate glyphs: }\n\n");
  441.         printf("dupglyph $%x $%x;\n",
  442.                Font->tf_LoChar + j, Font->tf_LoChar + i);
  443.         output++;
  444.         break;
  445.         }
  446.     }
  447.     }
  448.     if (output)
  449.     printf("\n");
  450. }
  451.  
  452. int
  453. main(int argc, char **argv)
  454. {
  455.     extern char    *optarg;
  456.     extern int        optind;
  457.     extern int        getopt(int, char **, char *);
  458.     int         errflg = 0;
  459.     int         c;
  460.  
  461.     while ((c = getopt(argc, argv, "f:l:svx:y:")) != -1) {
  462.     switch (c) {
  463.     case 'f':
  464.         TextAttr.tta_Name = optarg;
  465.         break;
  466.     case 'l':
  467.         linelength = atoi(optarg);
  468.         break;
  469.     case 's':
  470.         stretch = TRUE;
  471.         break;
  472.     case 'v':
  473.         verbose = TRUE;
  474.         break;
  475.     case 'x':
  476.         {
  477.         int x, y;
  478.         sscanf(optarg, "%d/%d", &x, &y);
  479.         TextTags[0].ti_Tag = TA_DeviceDPI;
  480.         TextTags[0].ti_Data = (x << 16) | (y & 0xFFFF);
  481.         }
  482.         break;
  483.     case 'y':
  484.         TextAttr.tta_YSize = atoi(optarg);
  485.         break;
  486.     case '?':
  487.         errflg++;
  488.         break;
  489.     }
  490.     }
  491.  
  492.     if (optind < argc)
  493.     TextAttr.tta_Name = argv[optind++];
  494.     if (optind < argc)
  495.     TextAttr.tta_YSize = atoi(argv[optind++]);
  496.  
  497.     if (errflg || optind > argc) {
  498.     printf(
  499. "Usage: bmfd -l<linelen> -x<xdpi>/<ydpi> name.font ysize\n");
  500.     exit(EXIT_FAILURE);
  501.     }
  502.  
  503.     atexit(cleanup);
  504.     openall();
  505.  
  506.     header();
  507.     dumpparameters();
  508.     dumpcharacters();
  509.     dupglyphdetect();
  510.  
  511. fail:
  512.     /* atexit function cleans up here */
  513. }
  514.